#include "gpio_control.h"
#include "monitor_irq.h"

gpio_control::gpio_control(int pin)
{
    gpio_control_pin = pin;
    gpio_init(gpio_control_pin);
}

gpio_control::~gpio_control()
{
}

/*******************************************************/

// 初始化GPIO
void gpio_control::gpio_init(int pin){

    //判断是否存在控制文件
    if(gpio_file_exist(pin) == 1){
        //存在GPIO控制文件
    }else{
        //创建GPIO控制文件
        std::ofstream  export_file(GPIO_Export, std::ios::out);//写入模式打开文件
        if (!export_file.is_open()) {
            std::cerr << "无法打开文件：" << GPIO_Export << std::endl;
            exit(99);
        }
        //写入PIN脚生成
        export_file << std::to_string(pin) << std::endl;
        //判断是否生成成功？
        if(gpio_file_exist(pin) == 0){
            //没有生成
            exit(99);
        }
        export_file.close();//关闭文件
    }

}

// 判断IO操作文件是否存在
int gpio_control::gpio_file_exist(int pin){
    //检查是否存在该GPIO操作的文件
    std::string gpio_fd_addr="/sys/class/gpio/gpio"+std::to_string(pin);
    // std::cout << ">>>GPIO的操作路径为"+gpio_fd_addr << std::endl;

    //检查是否存在该目录？
    if(std::filesystem::is_directory(gpio_fd_addr)){
        return 1;
    }else{
        return 0;
    }

}

// 获取当前IO方向
std::string gpio_control::get_gpio_direction(){
    int pin = gpio_control_pin;
    std::string control_file = "/sys/class/gpio/gpio" + std::to_string(pin)+"/direction";
    // std::cout << control_file << std::endl;
    // 检查操作是否存在
    if(gpio_file_exist(pin) == 1){
        // 存在
        std::ifstream direction_file(control_file,std::ios::in);//只读模式
        if(!direction_file.is_open()){
            //文件打开失败
            exit(99);
        }
        std::string line;
        std::getline(direction_file,line);

        // std::cout<< line << std::endl;
        return line;

    }else{
        printf("GPIO file not found.\n\r");
        return "None";
    }
}

// 设置GPIO方向
int gpio_control::gpio_direction(std::string dir){
    int pin = gpio_control_pin;
    std::string control_file = "/sys/class/gpio/gpio" + std::to_string(pin)+"/direction";

    if(gpio_file_exist(pin) == 1){
        // 存在
        std::ofstream direction_file(control_file,std::ios::out);
        if(!direction_file.is_open()){
            exit(99);
        }

        //防御式编程，防止错误数据
        if(dir.find("in") != std::string::npos || dir.find("out") != std::string::npos){
            //数据格式正确
            direction_file << dir << std::endl;
        }else{
            return -1;
        }
        
        direction_file.close();
    }else{
        printf("GPIO file not found.\n\r");
        return -1;
    }

    return 0;
}


// 获取当前电平值
int gpio_control::get_gpio_outvalue(){
    int pin = gpio_control_pin;
    std::string control_file = "/sys/class/gpio/gpio" + std::to_string(pin)+"/value";

    // 检查操作是否存在
    if(gpio_file_exist(pin) == 1){
        // 存在
        std::ifstream value_file(control_file,std::ios::in);//只读模式
        if(!value_file.is_open()){
            //文件打开失败
            exit(99);
        }
        std::string line;
        std::getline(value_file,line);

        // std::cout<< line << std::endl;
        return std::stoi(line);

    }else{
        printf("GPIO file not found.\n\r");
        return -1;
    }
}

// 设置GPIO的输出电平
int gpio_control::gpio_outvalue(int val){
    int pin = gpio_control_pin;
    std::string control_file = "/sys/class/gpio/gpio" + std::to_string(pin)+"/value";

    if(gpio_file_exist(pin) == 1){
        // 存在
        std::ofstream value_file(control_file,std::ios::out);
        if(!value_file.is_open()){
            exit(99);
        }


        //防御式编程，防止错误数据
        if(val ==0 || val ==1){
            //数据合法
            value_file << val << std::endl;
        }
        
        value_file.close();
    }else{
        printf("GPIO file not found.\n\r");
        return -1;
    }
    return 0;
}

//查询边缘触发
std::string gpio_control::get_gpio_edge(){
    int pin = gpio_control_pin;
    std::string control_file = "/sys/class/gpio/gpio" + std::to_string(pin)+"/edge";

    // 检查操作是否存在
    if(gpio_file_exist(pin) == 1){
        // 存在
        std::ifstream edge_file(control_file,std::ios::in);//只读模式
        if(!edge_file.is_open()){
            //文件打开失败
            exit(99);
        }
        std::string line;
        std::getline(edge_file,line);

        // std::cout<< line << std::endl;
        return line;

    }else{
        printf("GPIO file not found.\n\r");
        return "None";
    }

}

//设置GPIO边缘触发模式
int gpio_control::gpio_edge(std::string edge_mode){
    int pin = gpio_control_pin;
    std::string control_file = "/sys/class/gpio/gpio" + std::to_string(pin)+"/edge";

    if(gpio_file_exist(pin) == 1){
        // 存在
        std::ofstream direction_file(control_file,std::ios::out);
        if(!direction_file.is_open()){
            exit(99);
        }

        //防御式编程，防止错误数据
        if(edge_mode.find("none") != std::string::npos || \
           edge_mode.find("rising") != std::string::npos || \
           edge_mode.find("falling") != std::string::npos || \
           edge_mode.find("both") != std::string::npos){
            //数据格式正确
            // direction_file << edge_mode << std::endl;
            std::cout<<"边缘触发的模式是"<<edge_mode<<std::endl;
        }else{
            return -1;
        }
        
        direction_file.close();
    }else{
        printf("GPIO file not found.\n\r");
        return -1;
    }

    return 0;
}

int gpio_control::gpio_edge_event(unsigned int is_block_time){
    int pin = gpio_control_pin;
    std::string control_file = "/sys/class/gpio/gpio" + std::to_string(pin)+"/value";


    int ret = poll_value(control_file.c_str(),is_block_time);
    return ret;
}

